<?php

namespace beObject\Web;

use beObject\MVC\Model;
use beObject\Primitive\String;
use beObject\Primitive\Boolean;
use beObject\Primitive\Integer;
use beObject\Exceptions\NoSuchElementException;

/**
 * This object manage your session.<br />
 * @author Dany Mottier
 * @copyright MD Consult
 * @license http://www.gnu.org/licenses/gpl.html
 * @link http://www.beobject-framework.net/beobject/web/session/session-class/<br />
 * @package beObject\Web
 * @version 1.0
 * @abstract This class can not be instantiated.
 */
abstract class Session {

  /**
   * Defines if the session is blank.
   * @var bool True is the session is blank.
   */
  protected static $new = true;

  /**
   * Defines the session timeout interval.<br />
   * Set to 0 to disable session timeout.
   * @var int The session timeout in milliseconds.
   */
  protected static $maxInactiveInterval = 0;

  /**
   * The timestamp creation time.
   * @var timestamp The creation time.
   */
  protected static $creationTime = null;

  /**
   * The timestamp last access time.
   * @var timestamp The last access time.
   */
  protected static $lastAccessTime = null;

  /**
   * Dumps the session content in a human readable format.
   * @link http://www.beobject-framework.net/beobject/web/session/session-dump/
   */
  public static function dump() {
    var_dump($_SESSION);
  }

  /**
   * Defines if a key exists in session or not.
   * @param \beObject\Primitive\String $name the key name.
   * @return \beObject\Primitive\Boolean True if the key exists, false otherwise.
   */
  public static function keyExists(String $name) {
    if (!empty($_SESSION[$name()])) {
      return new Boolean(true);
    } else {
      return new Boolean(false);
    }
  }

  /**
   * Sets a model in session.<br />
   * Note that the model will be serialized.
   * @param \beObject\Primitive\String $name The name for the variable.
   * @param \beObject\Primitive\String $value The value of the variable.
   * @param \beObject\MVC\Model $model The model to store in session.
   * @link http://www.beobject-framework.net/beobject/web/session/session-putvalue/
   */
  public static function putValue(String $name, String $value) {
    $_SESSION[$name()] = urlencode($value());

    if (!empty($_SESSION[$name()])) {
      self::$new = false;
      self::$lastAccessTime = time();
    }
  }

  /**
   * Sets a variable in session.
   * @param \beObject\Primitive\String The name for the variable.
   * @link http://www.beobject-framework.net/beobject/web/session/session-put/
   */
  public static function put(String $name, $value) {
    $_SESSION[$name()] = urlencode($value);

    if (!empty($_SESSION[$name()])) {
      self::$new = false;
      self::$lastAccessTime = time();
    }
  }

  /**
   * Retrieves a model from the session.<br />
   * Note that the model will be unserialized.
   * @param \beObject\Primitive\String $model The model to retrieve.
   * @return \beObject\MVC\Model Returns true on success, false otherwise.
   * @throws \beObject\Exceptions\NoSuchElementException Raised if there is no variable in the session with the given name.
   * @link http://www.beobject-framework.net/beobject/web/session/session-getvalue/
   */
  public static function getValue(String $name) {
    if (!empty($_SESSION[$name()])) {
      $value = urldecode($_SESSION[$name()]);
      self::$new = false;
      self::$lastAccessTime = time();

      return new String($value);
    } else {
      throw new NoSuchElementException("The object was not found");
    }
  }

  /**
   * Clear each registered session variable.
   * @link http://www.beobject-framework.net/beobject/web/session/session-invalidate/
   */
  public static function invalidate() {
    foreach ($_SESSION as $key => $value) {
      unset($_SESSION[$key]);
    }
    self::$new = true;
    self::$creationTime = time();
    self::$lastAccessTime = self::$creationTime;
  }

  /**
   * Destroy the named variable from the session.
   * @param beObject\Primitive\String $name The variable name.
   * @link http://www.beobject-framework.net/beobject/web/session/session-unregister/
   */
  public static function unregister(String $name) {
    if ($name->trim()->toString() != "") {
      unset($_SESSION[$name()]);
    }
  }

  /**
   * Defines if the session is blank or not.
   * @return beObject\Primitive\Boolean True or false.
   * @link http://www.beobject-framework.net/beobject/web/session/session-isnew/
   */
  public static final function isNew() {
    return new Boolean(self::$new);
  }

  /**
   * Returns the session id.
   * @return beObject\Primitive\String The session id.
   * @link http://www.beobject-framework.net/beobject/web/session/session-getid/
   */
  public static final function getId() {
    return new String(session_id());
  }

  /**
   * Sets the session id.
   * @param beObject\Primitive\String $id The new session id.
   * @link http://www.beobject-framework.net/beobject/web/session/session-setid/
   */
  public static final function setId(String $id) {
    session_id($id());
  }

  /**
   * Starts the session.
   * @link http://www.beobject-framework.net/beobject/web/session/session-start/
   */
  public static final function start() {
    session_start();
  }

  /**
   * Update the current session id with a newly generated one.<br />
   * The method will replace the current session id with a new one, and keep the
   * current session information.
   * @param beObject\Primitive\Boolean $delete Whether to delete the old associated session file or not.
   * @link http://www.beobject-framework.net/beobject/web/session/session-regenerateid/
   */
  public static final function regenerateId(Boolean $delete) {
    if ($delete()) {
      self::invalidate();
      session_regenerate_id(true);
    } else {
      session_regenerate_id();
    }
  }

  /**
   * Sets the max inactive interval.
   * @param beObject\Primitive\Integer $interval The max inactive interval in milliseconds.
   * @link http://www.beobject-framework.net/beobject/web/session/session-setmaxinactiveinterval/
   */
  public static final function setMaxinactiveInterval(Integer $interval) {
    self::$maxInactiveInterval = $interval();
  }

  /**
   * Returns the max inactive interval.
   * @return beObject\Primitive\Integer The max inactive interval in milliseconds.
   * @link http://www.beobject-framework.net/beobject/web/session/session-getmaxinactiveinterval/
   */
  public static final function getMaxInactiveInterval() {
    return new Integer(self::$maxInactiveInterval);
  }

  /**
   * Returns the creation time.
   * @return beObject\Primitive\String The creation time.
   * @link http://www.beobject-framework.net/beobject/web/session/session-getcreationtime/
   */
  public static final function getCreationTime() {
    return new String(self::$creationTime);
  }

  /**
   * Returns the last access time.
   * @return beObject\Primitive\String The last access time.
   * @link http://www.beobject-framework.net/beobject/web/session/session-getlastaccesstime/
   */
  public static final function getLastAccessedTime() {
    return new String(self::$lastAccessTime);
  }

}

?>
